package com.java.hohenheim.springplatform.web.service;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.java.hohenheim.springplatform.data.model.account.LoginParams;
import com.java.hohenheim.springplatform.data.model.account.LoginResultModel;
import com.java.hohenheim.springplatform.data.model.account.UserInfoModel;
import com.java.hohenheim.springplatform.data.web.account.RegisterParams;
import com.java.hohenheim.springplatform.db.dao.AccountDAO;
import com.java.hohenheim.springplatform.db.dao.UserRoleDAO;
import com.java.hohenheim.springplatform.db.entity.AccountEntity;
import com.java.hohenheim.springplatform.db.entity.UserRoleEntity;
import com.java.hohenheim.springplatform.db.entity.UserRoleWithRole;
import com.java.hohenheim.springplatform.define.ResultCodes;
import com.java.hohenheim.springplatform.exception.PlatformException;
import com.java.hohenheim.springplatform.message.sms.ISmsSend;
import com.java.hohenheim.springplatform.redis.ops.RegisterVerificationCodeRedisOps;
import com.java.hohenheim.springplatform.web.jwt.UserTokenUtils;
import com.java.hohenheim.springplatform.web.service.login.ILogin;
import com.java.hohenheim.springplatform.web.jwt.JwtUtils;
import com.java.hohenheim.springplatform.web.service.register.IRegister;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author Hohenheim
 * @date 2020/7/19
 * @description 账户系统 Service
 */
@Service
@Slf4j
public class AccountService {
    @Autowired
    private RegisterVerificationCodeRedisOps mVerCodeRedis;

    @Autowired
    private AccountDAO mAccountDAO;
    @Autowired
    private UserRoleDAO mUserRoleDAO;

    @Autowired
    private Map<String, IRegister> mRegisterMethodMap;
    @Autowired
    private Map<String, ILogin> mLoginMethodMap;

    @Autowired
    private ISmsSend mSms;

    @Autowired
    private UserTokenUtils mUserTokenUtils;

    /**
     * 根据手机号码，创建验证码
     *
     * @param phone 手机号码
     */
    public boolean createPhoneRegisterVerCode(String phone) {
        // 检查该手机号码是否已被注册
        QueryWrapper<AccountEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        AccountEntity accountEntity = mAccountDAO.getOne(queryWrapper, false);
        if (null != accountEntity) {
            throw new PlatformException(ResultCodes.PHONE_HAS_BEEN_REGISTERED);
        }

        if (StringUtils.isNotBlank(mVerCodeRedis.getBeenSendCode(phone))) {
            //未到验证码发送时间间隔
            throw new PlatformException(ResultCodes.REGISTER_VERIFICATION_CODE_SEND_BUSY);
        }

        // 检查该手机号码是否已存在验证码
        boolean createCodeResult = true;
        String code = mVerCodeRedis.getVerificationCode(phone);
        if (StringUtils.isBlank(code)) {
            //创建注册码，并缓存
            code = RandomUtil.randomNumbers(6);
            createCodeResult = mVerCodeRedis.saveVerificationCode(phone, code);
        }

        if (createCodeResult) {
            //将验证码通过短信发送，如果发送失败，删除已缓存的验证码
            if (!mVerCodeRedis.saveBeenSendCode(phone, code)) {
                throw new PlatformException(ResultCodes.REGISTER_VERIFICATION_CODE_SEND_FAIL);
            }

            boolean sendResult = mSms.sendVerificationCodeSms(phone, code);
            if (!sendResult) {
                mVerCodeRedis.delBeenSendCode(phone);
                throw new PlatformException(ResultCodes.REGISTER_VERIFICATION_CODE_SEND_FAIL);
            }
        }

        return createCodeResult;
    }

    /**
     * 注册
     *
     * @param param        注册参数
     * @param registerType 注册类型
     */
    public boolean register(RegisterParams param, String registerType) {
        String registerKey = registerType + "Register";
        IRegister registerMethod = mRegisterMethodMap.get(registerKey);
        if (null == registerMethod) {
            throw new PlatformException(ResultCodes.NO_REGISTER_METHOD);
        }

        return registerMethod.register(param);
    }

    /**
     * 登录
     *
     * @param param     登录参数
     * @param loginType 登录类型
     * @return 用户信息
     */
    public LoginResultModel login(LoginParams param, String loginType) {
        String loginMethodKey = loginType + "Login";
        ILogin loginMethod = mLoginMethodMap.get(loginMethodKey);
        if (null == loginMethod) {
            throw new PlatformException(ResultCodes.NO_LOGIN_METHOD);
        }

        UserInfoModel userInfoModel = loginMethod.login(param);
        LoginResultModel loginResult = new LoginResultModel();
        loginResult.setUserInfo(userInfoModel);
        loginResult.setToken(mUserTokenUtils.createUserToken(userInfoModel.getUserId()));

        return loginResult;
    }

    /**
     * 查詢用戶信息
     *
     * @param userId 用户ID
     */
    @Cacheable(value = "user" ,key = "#userId")
    public AccountEntity getAccountInfo(long userId) {
        return mAccountDAO.getById(userId);
    }

    /**
     * 查询用户角色信息
     */
    public UserRoleWithRole getUserRoles(long userId) {
        return mUserRoleDAO.getBaseMapper().getUserRoles(userId);
    }
}